<?
require_once('ConverterBase.php');

class DateConverter extends ConverterBase {
	private $format= '%Y-%m-%d',$dayPosition,$monthPosition,$yearPosition,$useUnixTime= false;

	// ACCESSORS
	/**
	 * Set a strftime compatible date format.
	 * The format is used to convert dates from or to strings.
	 */
	public function setFormat($value) { $this->format= $value; return $this; }
	public function getFormat() { return $this->format; }

	public function setDayPosition($value) { $this->dayPosition= intval($value); return $this; }
	public function getDayPosition() { return $this->dayPosition; }

	public function setMonthPosition($value) { $this->monthPosition= intval($value); return $this; }
	public function getMonthPosition() { return $this->monthPosition; }

	public function setYearPosition($value) { $this->yearPosition= intval($value); return $this; }
	public function getYearPosition() { return $this->yearPosition; }

	public function setUseUnixTime($bool) { $this->useUnixTime= (bool)$bool; return $this; }
	public function getUseUnixTime() { return $this->useUnixTime; }

	private function guessPositions() {
		$positions= array();
		// extact strftime specifiers
		$matches= array();
		preg_match_all("/\%\w/",$this->getFormat(),$matches);
		// if specifiers are found
		if (isset($matches[0]) && !empty($matches[0])) {
			$pos= 1;
			// check each specifier according to valid strftime() arguments and assign a position
			foreach ($matches[0] as $specifier) {
				if (ereg("[D]",$specifier)) {
					$positions['day']= 2;
					$positions['month']= 1;
					$positions['year']= 3;
					break;
				}
				else if (ereg("[aAdej]",$specifier) && empty($positions['day'])) $positions['day']= $pos++;
				else if (ereg("[bBhm]",$specifier) && empty($positions['month'])) $positions['month']= $pos++;
				else if (ereg("[CgGyY]",$specifier) && empty($positions['year'])) $positions['year']= $pos++;
				// when 3 positions are filled
				if ($pos=== 4) break;
			}
			
		}
		// check positions found during parsing
		if (count($positions)<3)
			throw new ConverterException($this,'unable_to_guess_positions');
		return $positions;
	}

	private function getPositions() {
		// make sure positions are set
		if ($this->getDayPosition() && $this->getMonthPosition() && $this->getYearPosition())
			return array('day'=>$this->getDayPosition(),'month'=>$this->getMonthPosition(),'year'=>$this->getYearPosition());
		return $this->guessPositions();
	}
	protected function toDatatype($string) {
		if (!trim($string)) return null;

		$matches= array();
		preg_match_all("/(\d+)\D(\d+)\D(\d+)/",trim($string),$matches);
		// not all three values are present
		if (empty($matches[0])) throw new ConverterException($this,'invalid_date',$string);
		// assign values according to their position
		$positions= $this->getPositions();
		$day= (int)$matches[$positions['day']][0];
		$month= (int)$matches[$positions['month']][0];
		$year= (int)$matches[$positions['year']][0];
		// check values
		if ($day< 1 || $day> 31) throw new ConverterException($this,'invalid_day',$string);
		if ($month< 1 || $month> 12) throw new ConverterException($this,'invalid_month',$string);
		// create date
		if ($this->getUseUnixTime())
			return mktime(0,0,0,$month,$day,$year);
		else
			return new DateTime($year.'-'.$month.'-'.$day);
	}
	protected function toString($object) {
		if ($this->getUseUnixTime())
			return strftime($this->getFormat(),$object);
		else
			return strftime($this->getFormat(),$object->format('U'));
	}
}
